package com.atguigu.guli.service.ucenter.service.impl;

import com.atguigu.guli.common.util.HttpClientUtils;
import com.atguigu.guli.common.util.MD5;
import com.atguigu.guli.service.base.dto.MemberDto;
import com.atguigu.guli.service.base.exception.GuliException;
import com.atguigu.guli.service.base.helper.JwtHelper;
import com.atguigu.guli.service.base.helper.JwtInfo;
import com.atguigu.guli.service.base.result.ResultCodeEnum;
import com.atguigu.guli.service.ucenter.entity.Member;
import com.atguigu.guli.service.ucenter.entity.form.LoginForm;
import com.atguigu.guli.service.ucenter.entity.form.RegisterForm;
import com.atguigu.guli.service.ucenter.mapper.MemberMapper;
import com.atguigu.guli.service.ucenter.properties.UcenterProperties;
import com.atguigu.guli.service.ucenter.service.MemberService;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpSession;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.Map;
import java.util.UUID;

/**
 * <p>
 * 会员表 服务实现类
 * </p>
 *
 * @author atguigu
 * @since 2021-08-10
 */
@Service
public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member> implements MemberService {

    @Override
    public void register(RegisterForm registerForm) {
        //用户是否被注册
        QueryWrapper<Member> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("mobile",registerForm.getMobile());
        Integer count = baseMapper.selectCount(queryWrapper);
        if (count > 0){
            throw new GuliException(ResultCodeEnum.REGISTER_MOBLE_ERROR);
        }

        //会员注册
        Member member = new Member();
        member.setMobile(registerForm.getMobile());
        member.setNickname(registerForm.getNickname());
        member.setPassword(MD5.encrypt(registerForm.getPassword()));
        member.setAvatar("https://online-edu0325.oss-cn-shanghai.aliyuncs.com/avatar/default.jpg");
        member.setDisabled(false);

        baseMapper.insert(member);


    }

    @Override
    public String login(LoginForm loginForm) {
        String mobile = loginForm.getMobile();
        String password = loginForm.getPassword();

        //校验手机号
        //用户是否被注册
        QueryWrapper<Member> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("mobile",mobile);
        Member member = baseMapper.selectOne(queryWrapper);
        if (member == null){
            throw new GuliException(ResultCodeEnum.LOGIN_MOBILE_ERROR);
        }
        //校验密码
        if(!MD5.encrypt(password).equals(member.getPassword())){
            throw new GuliException(ResultCodeEnum.LOGIN_PASSWORD_ERROR);
        }
        //用户是否被禁用
        if (member.getDisabled()){
            throw new GuliException(ResultCodeEnum.LOGIN_DISABLED_ERROR);
        }
        //生成jwt
        JwtInfo jwtInfo = new JwtInfo(member.getId(),
                member.getNickname(),
                member.getAvatar());
        String token = JwtHelper.createToken(jwtInfo);
        return token;

    }

    @Autowired
    UcenterProperties ucenterProperties;

    @Override
    public String wxLogin(HttpSession session) {
        try {
            String url = "https://open.weixin.qq.com/connect/qrconnect?" +
                    "appid=%s" +
                    "&redirect_uri=%s" + //http://localhost:8160/api/ucenter/wx/callback
                    "&response_type=code" +
                    "&scope=snsapi_login" +
                    "&state=%s" + //随机数
                    "#wechat_redirect";


            String uri = URLEncoder.encode(ucenterProperties.getRedirectUri(), "UTF-8");
            String state = UUID.randomUUID().toString().replace("-","");
            url = String.format(url, ucenterProperties.getAppId(),uri, state);
            session.setAttribute("wx_open_state", state);
            return "redirect:"+url;
        } catch (Exception e) {
            throw new GuliException(ResultCodeEnum.ILLEGAL_CALLBACK_REQUEST_ERROR,e);
        }
    }

    @Override
    public String wxCallback(String code, String state, HttpSession session) {

        //回调被拉起，并获得code和state参数
        System.out.println("callback被调用");
        System.out.println("code = " + code);
        System.out.println("state = " + state);
        //校验state是否正确
        if(StringUtils.isEmpty(code) || StringUtils.isEmpty(state) ){
            log.error("非法回调请求");
            throw new GuliException(ResultCodeEnum.ILLEGAL_CALLBACK_REQUEST_ERROR);
        }
        String sessionState = (String)session.getAttribute("wx_open_state");
        if(!state.equals(sessionState)){
            log.error("非法回调请求");
            throw new GuliException(ResultCodeEnum.ILLEGAL_CALLBACK_REQUEST_ERROR);
        }
        try {
            //通过code获取access_token 相当于用户的授权
            //根据code值获取wx用户的数据: 相当于用户的授权
            //app的身份： appId+appSecurity:
            String url = "https://api.weixin.qq.com/sns/oauth2/access_token?" +
                    "appid="+ucenterProperties.getAppId()+"&" +
                    "secret="+ucenterProperties.getAppSecret()+"&" +
                    "code="+code+"&" +
                    "grant_type=authorization_code";

            //java代码中访问 获取AccessToken的接口地址，获取授权字符串
            // 创建客户端对象
            HttpClientUtils client = new HttpClientUtils(url);
            // 发送请求
            client.get();
            // 获取响应结果
            String content = client.getContent();
            System.out.println("content = "+content);
            Gson gson = new Gson();
            Map map = gson.fromJson(content,Map.class);
            if (map.get("errcode")!=null){
                throw new GuliException(ResultCodeEnum.ILLEGAL_CALLBACK_REQUEST_ERROR);
            }
            String accessToken = map.get("access_token").toString();
            String openid = map.get("openid").toString();
            System.out.println(openid);
            //判断数据库中是否有openid wx用户的数据，
            // 如果没有 将他保存到我们的数据库中，如果有直接获取数据库wx用户数据显示
            LambdaQueryWrapper<Member> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Member::getOpenid,openid);
            Member member = this.getOne(queryWrapper);
            if (member == null){
                //使用openid和AccessToken获取该用户在微信中的数据/sns/userinfo
                url = "https://api.weixin.qq.com/sns/userinfo?" +
                        "access_token="+ accessToken +
                        "&openid="+ openid;
                client = new HttpClientUtils(url);
                client.get();
                content = client.getContent();
                System.out.println("用户信息content = "+content);
                map = gson.fromJson(content,Map.class);
                if (map.get("errcode")!=null){
                    throw new GuliException(ResultCodeEnum.ILLEGAL_CALLBACK_REQUEST_ERROR);
                }
                String nickname = map.get("nickname").toString();
                Integer sex = new BigDecimal(map.get("sex").toString()).intValue();
                String headimgurl = map.get("headimgurl").toString();
                //将用户数据存到数据库
                member = new Member();
                member.setAvatar(headimgurl);
                member.setNickname(nickname);
                member.setSex(sex);
                member.setOpenid(openid);
                this.save(member);
                System.out.println(nickname + "用户第一次使用微信登录");
            }else{
                System.out.println(member.getNickname() + "该用户不是新用户");
                //判断member对象的更新时间，和当前的时间日期比较，如果超过某段时间 再次查询wx后台获取wx用户端的数据更新数据库
            }

            JwtInfo jwtInfo = new JwtInfo();
            jwtInfo.setAvatar(member.getAvatar());
            jwtInfo.setNickname(member.getNickname());
            jwtInfo.setId(member.getId());

            String token = JwtHelper.createToken(jwtInfo);

            //如果授权登录，获取到微信用户的数据，让用户跳转到登录成功的页面
            return "redirect:http://localhost:3000?token="+token;

        } catch (Exception e) {
            throw new GuliException(ResultCodeEnum.ILLEGAL_CALLBACK_REQUEST_ERROR,e);
        }
    }

    @Override
    public MemberDto getMemberDtoById(String memberId) {
        Member member = baseMapper.selectById(memberId);
        MemberDto memberDto = new MemberDto();
        BeanUtils.copyProperties(member,memberDto);
        return memberDto;
    }

    @Override
    public Integer countRegisterNum(String day) {
        return baseMapper.selectRegisterNumByDay(day);
    }


}
